package process

import (
    "encoding/binary"
    "encoding/json"
    "fmt"
    "gitee.com/HyoJoo-W/ChatRoom/client/utils"
    "gitee.com/HyoJoo-W/ChatRoom/common/entity"
    "gitee.com/HyoJoo-W/ChatRoom/common/message"
    "net"
)

type UserProcess struct {
}

func (this *UserProcess) Login(userId int, userPwd string) (err error) {
    //1.连接到服务器
    conn, err := net.Dial("tcp", "localhost:8889")
    if err != nil {
        fmt.Println("net.Dial err=", err)
        return
    }
    defer conn.Close()

    //2.准备通过conn发送消息给服务器
    var mes message.Message
    mes.Type = message.LoginMesType

    //3.创建一个LoginMes结构体
    var loginMes message.LoginMes
    loginMes.UserId = userId
    loginMes.UserPwd = userPwd

    //4.将loginMes序列化
    data, err := json.Marshal(loginMes)
    if err != nil {
        fmt.Println("json.Marshal err=", err)
        return
    }

    //5.发送消息给服务器端
    mes.Data = string(data)

    //6.将mes进行序列化
    data, err = json.Marshal(mes)
    if err != nil {
        fmt.Println("json.Marshal err=", err)
        return
    }

    //7.此时data就是需要发送的消息
    //7.1 先发送data的长度
    //将data的长度转换为一个表示长度的byte切片
    var pkgLen = uint32(len(data))
    var buf [4]byte
    binary.BigEndian.PutUint32(buf[0:4], pkgLen)

    //发送长度
    n, err := conn.Write(buf[:4])
    if n != 4 || err != nil {
        fmt.Println("conn.Write(bytes) err= ", err)
        return
    }

    //fmt.Println("客户端发送的数据为data =",string(data))
    //发送消息内容
    _, err = conn.Write(data)
    if err != nil {
        fmt.Println("conn.Write(data) err = ", err)
        return
    }

    //处理服务器端返回的数据
    tf := &utils.Transfer{
        Conn: conn,
    }
    mes, err = tf.ReadPkg()
    if err != nil {
        fmt.Println("[登录]读取服务器端响应数据失败, err = ", err)
    }
    //将mes的data部分反序列化为LoginResMes类型
    var loginResMes message.LoginResMes
    err = json.Unmarshal([]byte(mes.Data), &loginResMes)
    if loginResMes.Code == 200 {
        //1 初始化CurUser
        CurUser.Conn = conn
        CurUser.UserId = userId
        CurUser.UserStatus = message.UserOnline

        //登录成功,显示在线用户列表
        fmt.Println("当前在线用户列表如下:")
        for _, v := range loginResMes.UserIds {
            //不显示自己
            if v == userId {
                continue
            }
            fmt.Println("用户id: \t", v)

            //2 初始化客户端维护的在线用户表
            user := &entity.User{
                UserId:     v,
                UserStatus: message.UserOnline,
            }
            onlineUsers[v] = user
        }
        fmt.Println()

        //启动协程保持与服务器端的通信
        //保证服务器端推送的消息,客户端可以及时接收
        go serverProcessMes(conn)
        //1 显示登录成功后的菜单
        for {
            ShowMenu()
        }
    } else {
        fmt.Println(loginResMes.Error)
    }
    return
}

func (this *UserProcess) Register(userId int, userPwd string, userName string) (err error) {
    //1.连接到服务器
    conn, err := net.Dial("tcp", "localhost:8889")
    if err != nil {
        fmt.Println("net.Dial err=", err)
        return
    }
    defer conn.Close()

    //2.准备通过conn发送消息给服务器
    var mes message.Message
    mes.Type = message.RegisterMesType

    //3.创建一个RegisterMes结构体
    var registerMes message.RegisterMes
    registerMes.User.UserId = userId
    registerMes.User.UserPwd = userPwd
    registerMes.User.UserName = userName

    //4.将registerMes序列化
    data, err := json.Marshal(registerMes)
    if err != nil {
        fmt.Println("json.Marshal err=", err)
        return
    }

    //5.发送消息给服务器端
    mes.Data = string(data)

    //6.将mes进行序列化
    data, err = json.Marshal(mes)
    if err != nil {
        fmt.Println("json.Marshal err=", err)
        return
    }

    //7 发送注册请求
    tf := &utils.Transfer{
        Conn: conn,
    }
    err = tf.WritePkg(data)
    if err != nil {
        fmt.Println("[注册]客户端发送注册请求失败, err = ", err)
        return
    }

    //8 处理服务器端响应的消息
    mes, err = tf.ReadPkg()
    if err != nil {
        fmt.Println("[注册]读取服务器端响应数据失败, err = ", err)
    }

    //将mes的data部分反序列化为RegisterResMes类型
    var registerResMes message.RegisterResMes
    err = json.Unmarshal([]byte(mes.Data), &registerResMes)

    fmt.Println("test code = ", registerResMes.Code)

    if registerResMes.Code == 200 {
        //注册成功
        fmt.Println("[注册]注册成功！")
    } else {
        fmt.Println(registerResMes.Error)
    }
    return
}
